﻿<template>
	<div class="my-cell" :class="{ active: showSelected && selected }">
		<div class="my-cell-check" v-if="isCheck">
			<el-checkbox size="large" :checked="check" @change="onCheckChange" />
		</div>
		<div class="my-cell-icon" v-if="$slots.icon || icon">
			<slot name="icon">
				<MyImg :preview-src-list="[getPreviewImgUrl(icon)]" style="width: 100%; height: 100%" fit="contain"
					:src="getImgUrl(icon)">
					<template #error>
						<el-icon class="cell-icon">
							<Picture />
						</el-icon>
					</template>
				</MyImg>
			</slot>
		</div>
		<div class="my-cell-constant" @click="$emit('click')">
			<div v-if="$slots.title || title" class="my-cell-title line-clamp2">
				<slot name="title">
					<span>{{ getValue(title) }}</span>
				</slot>
			</div>
			<template v-if="$slots.label || label">
				<slot name="label">
					<div class="my-cell-label line-clamp2">
						<span>{{ getValue(label) }}</span>
					</div>
				</slot>
			</template>
			<div class="my-cell-tags" v-if="showTags">
				<slot name="tags">
					<el-tag v-if="tag" effect="plain" size="small">{{ getValue(tag, 8) }}</el-tag>
					<template v-for="btn in tags2" :key="btn.label">
						<el-tag effect="plain" :type="btn.type" v-if="btn.label && checkIf(btn.vif)"
							@click.stop="doClick(btn.click)" size="small">{{ getValue(btn.label, 8) }}</el-tag>
					</template>
				</slot>
			</div>
			<div class="my-cell-action" v-if="$slots.actions || actions">
				<slot name="actions">
					<el-space>
						<template v-for="btn in actions" :key="btn.label">
							<el-button  :type="btn.type" v-if="btn.label && checkIf(btn.vif)" :size="btn.size"
								@click.stop="doClick(btn.click)">{{ btn.label }}</el-button>
						</template>
					</el-space>
				</slot>
			</div>
			<div class="my-cell-link" v-if="$slots.links || links">
				<slot name="links">
					<el-space spacer="|" wrap>
						<template v-for="btn in links" :key="btn.label">
							<el-link :type="btn.type" v-if="btn.label && checkIf(btn.vif)"
								@click.stop="doClick(btn.click)">{{ btn.label }}</el-link>
						</template>
					</el-space>
				</slot>
			</div>
		</div>
		<div class="my-cell-value line-clamp1" v-if="$slots.value || value" @click="$emit('click')">
			<slot name="value">
				<el-tag v-bind="valueTagAttr" v-if="getValue(value, 8)">{{ getValue(value, 8) }}</el-tag>
			</slot>
		</div>
		<div class="my-cell-righ" v-if="$slots.right || isLink" @click="$emit('click')">
			<slot name="right">
				<el-icon :size="24">
					<ArrowRight />
				</el-icon>
			</slot>
		</div>
		<div class="my-cell-newline" v-if="$slots.newline">
			<slot name="newline"></slot>
		</div>
	</div>
</template>

<script>
import store from "./store";
import { ArrowRight, Picture } from "@element-plus/icons-vue";
import { computed } from 'vue';
import Utils from './Utils.js';

export default {
	name: "MyCell",
	components: { ArrowRight, Picture },
	emits: ["click", "update:check", "update:formData", "delete"],
	props: {
		tbname: String,
		formData: Object,
		title: String,
		label: String,
		value: [String, Number],
		tag: String,
		icon: String,
		isLink: {
			type: Boolean,
			default: true
		},
		actions: Array,
		links: Array,
		tags: [String, Array],
		cfg: Object,
		selected: Boolean,
		iconSize: {
			type: String,
			default: '48px'
		},
		isCheck: Boolean,
		check: Boolean,
		valueTagAttr: Object,
		showSelected: {
			type: Boolean,
			default: true
		}
	},
	inject: {
        MyPage: { default: null },
        MyListPage: { default: null },
    },
	data() {
		return {
			columns: null,
			//动态增加的计算字段
			computeData: {},
		};
	},
	created() {
		if (this.tbname) {
			this.$server.getDM(this.tbname).then(tb => {
				this.columns = tb.columns;
			});
		}
		this.proceformExtend();
	},
	methods: {
		getValue(val, maxLen) {
			let str = val ? String(val) : "";
			if (str.startsWith("format_")) {
				let func = this[str];
				if (func && typeof (func) == "function") {
					return func.apply(this,[this.formData]);
				}
			}
			if (val && this.formData && this.columns) {
				str = this.$server.dm_format(this.columns, this.formData, val) || val;
			}

			if (maxLen && str.length > maxLen) {
				str = str.substring(0, maxLen) + "...";
			}
			if(str.startsWith("${")){
				str = "";
			}
			return str;
		},
		getPreviewImgUrl(url) {
			if (url && url.startsWith("${")) {
				url = this.getValue(url);
			}
			let str = store.getUrl(url);
			if (str.endsWith(".thumb.jpg")) {
				return str.substring(0, str.length - 10);
			}
			return str;
		},
		getImgUrl(url) {
			if (url && url.startsWith("${")) {
				url = this.getValue(url);
			}
			return store.getUrl(url);
		},
		checkIf(vif) {
			if (!vif) {
				return true;
			}
			if (typeof (vif) == "string" && !(vif in this.computeData)) {
				let key = "methods." + vif;
				vif = Utils.getValByKey(this.cfg, key);
			}

			if (typeof vif == "function") {
				return vif.apply(this,[this.formData]);
			} else if (typeof vif == "string") {
				return this.computeData[vif] != false;
			}
			return true;
		},
		doClick(fun) {
			if(!fun)return;
			let funName = "";
			if (typeof (fun) == "string") {
				funName = fun;
				let key = "methods." + fun;
				fun = Utils.getValByKey(this.cfg, key);
			}
			if (typeof (fun) == "function") {
				fun.apply(this,[this.formData]);
			} else {
				$msg.error("找不到自定义方法：" + funName);
			}
		},
		proceformExtend() {
			if (this.cfg) {
				//动态添加watch
				this.proceFormWatch(this.cfg.watch);
				//动态添加计算属性
				this.proceFormComputed(this.cfg.computed);
				//添加动态method
				this.proceFormMethods(this.cfg.methods);
			}
		},
		proceFormWatch(w) {
			for (let key in w) {
				let val = w[key];
				if (typeof val == "function") {
					this.$watch(key, (newVal, oldVal) => {
						try {
							val.apply(this, [newVal, oldVal]);
						} catch (e) {
							alert("自定义watch执行错误:" + e);
						}
					},
						{ deep: true });
				}
			}
		},
		proceFormComputed(c) {
			for (let key in c) {
				let cfield = c[key];
				if (typeof cfield == "function") {
					this.computeData[key] = computed(() => cfield.apply(this));
				} else if (typeof cfield.get == "function") {
					this.computeData[key] = computed({
						get: () => {
							try {
								return cfield.get.apply(this);
							} catch (e) {
								console.log("计算字段取值出错：" + key);
							}
						},
						set: (newValue) => {
							try {
								cfield.set.apply(this, [newValue]);
							} catch (e) {
								console.log(
									"计算字段Set出错：" + key + "," + newValue
								);
							}
						},
					});
				}
			}
		},
		proceFormMethods(m) {
			for (let key in m) {
				let func = m[key];
				if (typeof func == "function") {
					this[key] = func.bind(this);
				} else {
					console.log("method定义错误：" + key);
				}
			}
		},
		onCheckChange(val) {
			this.$emit("update:check", val);
		}
	},
	computed: {
		tags2() {
			if (!this.tags) return [];
			if (typeof (this.tags) == "string") {
				let str = this.tags;
				if (this.tags.startsWith("${")) {
					let str1 = this.getValue(this.tags);
					let items = str1.split(/,|；|，|;/).filter(p => p.trim().length > 0).map(p => ({label: p}));
					return items;
				}
				if (str.startsWith("format_")) {
					let func = this[str];
					if (func && typeof (func) == "function") {
						var str2  = func.apply(this,[this.formData]);
						if(str2 && typeof(str2)=="string"){
							return str2.split(";").filter(p => p.trim().length > 0).map(p => ({label: p}));
						}
						return str2;
					}
				}

				return this.tags.split(/,|；|，|;/).map(p => this.getValue(p)).filter(p => p.trim().length > 0).map(p=>({label:p}));
			}
			return this.tags;

		},
		showTags() {
			return this.$slots.tags || (this.tags && this.tags.length > 0) || this.tag;
		}
	},
	watch: {
		cfg(val) {
			this.proceformExtend();
		}
	},
};
</script>

<style scoped>
.my-cell {
	margin: 4px;
	padding: 4px 2px;
	cursor: pointer;
	position: relative;
	display: flex;
	box-sizing: border-box;
	font-size: 13px;
	border-bottom: 1px solid #eee;
	line-height: 17px !important;
	flex-wrap: wrap;
}

.my-cell:hover {
	background-color: #ecf5ff;
}

.active {
	background-color: #ecf5ff;
}

.my-cell-check {
	width: 32px;
	margin: auto;
}

.my-cell-icon {
	width: v-bind(iconSize);
	height: v-bind(iconSize);
	border-radius: 10px;
	margin-right: 6px;
}

.my-cell-constant {
	flex: 1;
	display: inline-grid;
}



.my-cell-title {
	font-size: 1.15em;
	font-weight: bold;
}

.my-cell-action {}

.my-cell-tags {
	padding: 2px 0;
}

.my-cell-link {}

.my-cell-label {
	padding: 2px 0;
	color: #808080;
	white-space: pre-wrap;
}

.my-cell-value {
	/* text-align: right;
	flex: 1;
	vertical-align: middle; */
}

.my-cell-value::before {
	content: "";
	width: 0;
	height: 100%;
	display: inline-block;
	position: relative;
	vertical-align: middle;
	background: #f00;
}

.my-cell-righ {
	min-width: 24px;
	vertical-align: middle;
}

.my-cell-icon:last-child {
	width: 20px;
	height: 20px;
	color: #808080;
}

.my-cell-righ::before {
	content: "";
	width: 0;
	height: 100%;
	display: inline-block;
	position: relative;
	vertical-align: middle;
	background: #f00;
}

.line-clamp1 {
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 1;
	-webkit-box-orient: vertical;
}

.line-clamp2 {
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
}

.line-clamp3 {
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
}


.line-clamp4 {
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
}


.cell-icon {
	font-size: v-bind(iconSize);
	color: #cecece;
}

.my-cell-newline {
	clear: both;
	display: block;
	width: 100%;
}
</style>